package {
	import character.Monster;
	import character.Human;
	import character.Car;
	import org.flixel.FlxObject;
	import org.flixel.FlxSprite;
	import org.flixel.FlxG;
	import states.GamePlayState;
	import events.GameEvent;
	import events.GameEventManager;
	/**
	 * @author NilsIH
	 */
	public class TileEffect extends NiloGroup{
		
		[Embed(source="../img/infection.png")] private var InfectionGFX:Class;
		[Embed(source="../img/infect.png")] private var InfectGFX:Class;
		[Embed(source="../img/planten.png")] private var Plant:Class;
		[Embed(source="../img/ild.png")] private var FireGFX:Class;
		[Embed(source="../img/lava.png")] private var Lava:Class;
		
		
		public var tile:NiloTile;
		public var type:String;
		private var _canSpread:Boolean;
		private var _level:int;
		private var _maxLevel:int;
		private var _gameEventManager:GameEventManager;
		private var _spreadEvent:GameEvent;
		private var _sprite:FlxSprite;
		private var _infestAnimation:FlxSprite;
		private var _monster:Monster;
		private var _flameSprite:FlxSprite;
		private var _lavaSprite:FlxSprite;
		
		public function TileEffect(){
			
			_gameEventManager = new GameEventManager();
			add(_gameEventManager);
			
			_canSpread = true;
			
			
			
			_sprite = new FlxSprite();
			_sprite.loadGraphic(InfectionGFX, true, false, 50, 50);
			
			_flameSprite = new FlxSprite();
			_flameSprite.loadGraphic(FireGFX, true, false, 56, 56);
			_flameSprite.addAnimation("burn", [0, 1, 2, 3, 4], 10);
			
			_lavaSprite = new FlxSprite();
			_lavaSprite.loadGraphic(Lava);
			_sprite.visible = false;
			_flameSprite.visible = false;
			_lavaSprite.visible = false;
			add(_lavaSprite);
			add(_sprite);
			add(_flameSprite);
			
			setColliderGroup(GamePlayState.tileColliders);
		}
		
		override protected function setupColliders():void{
			addCollider(new Collider(0, 0, 50, 50));
		}
		
		public function initialize(tile:NiloTile, type:String):TileEffect {
			
			_gameEventManager.clear();
			if (this.type != "infest" || type == "explode") _sprite.visible = false;
			_flameSprite.visible = false;
			_lavaSprite.visible = false;
			
			this.tile = tile;
			this.type = type;
			this.x = tile.x;
			this.y = tile.y;
			_sprite.x = tile.x;
			_sprite.y = tile.y;
			_flameSprite.x = tile.x;
			_flameSprite.y = tile.y;
			_lavaSprite.x = tile.x;
			_lavaSprite.y = tile.y;
			_level = 0;
			_maxLevel = 0;
			if (type == "infest"){
				_infestAnimation = new FlxSprite(-15, -30);
				_infestAnimation.loadGraphic(InfectGFX, true, false, 80, 80);
				_infestAnimation.addAnimation("infeststart", [0, 1, 2, 3, 4, 5, 6, 7], 12);
				_infestAnimation.addAnimationCallback(acb);
				add(_infestAnimation);
				_infestAnimation.play("infeststart");
				//_sprite.visible = true;
			}
			else if (type == "fire"){
				_flameSprite.visible = true;
				_flameSprite.play("burn");
				_gameEventManager.add(new GameEvent(cooldown, 12));
			}
			else if (type == "explode" || type == "passiveexplode"){
				var adjacent:Array = this.tile.adjacentTiles;
				var i:uint = 0;
				if (type == "passiveexplode"){
					for (i = 0; i < adjacent.length; i++){
						(adjacent[i] as NiloTile).infuseTileWith("infest");
					}
					clear();
					kill();
					if (tile.layeredAbove) GamePlayState.tileEffects2.remove(this);
					else GamePlayState.tileEffects.remove(this);
				}
				else {
					_lavaSprite.visible = true;
					_gameEventManager.add(new GameEvent(cooldown, 40));
					for (i = 0; i < adjacent.length; i++){
						(adjacent[i] as NiloTile).infuseTileWith("infest");
					}
				}
				GamePlayState.rainFire(3);
			}
			
			
			_gameEventManager.add(new GameEvent(doSpread, spreadTime, canStillSpread, -1));
			//	Experiment:
			if (tile.layeredAbove) GamePlayState.tileEffects2.add(this);
			else GamePlayState.tileEffects.add(this);
			
			return this;
		}
		
		public function levelUp():void{
			_level++;
		}
		
		public function doSpread(gameEvent:GameEvent):void {
			var adjacent:Array = this.tile.adjacentTiles;
			var spreadable:Array = [];
			var definatelySpreadable:Array = [];
			for (var i:uint = 0; i < adjacent.length; i++){
				if (checkIfTileIsDefinatelySpreadable(adjacent[i])){
					definatelySpreadable.push(adjacent[i]);
				}
				else if (checkIfTileIsSpreadable(adjacent[i])){
					spreadable.push(adjacent[i]);
				}
			}
			if (definatelySpreadable.length > 0){
				
				var deftile:NiloTile = NiloUtils.getRandomElement(definatelySpreadable) as NiloTile;
				deftile.infuseTileWith(this.type == "explode" ? "fire" : this.type);
				determineGFX();
			}
			if (spreadable.length > 0){
				var tile:NiloTile = NiloUtils.getRandomElement(spreadable) as NiloTile;
				if (type != "infest"){
					if (NiloUtils.numberIsOver(0.9)){
						// Spread fire:
						tile.infuseTileWith(this.type == "explode" ? "fire" : this.type);
					}
				}
				else {
					tile.infuseTileWith(this.type == "explode" ? "fire" : this.type);
				}
				determineGFX();
			}
			if ((type == "explode") && (NiloUtils.randomBoolean())){
				GamePlayState.rainFire(1);
			}
			gameEvent.timedelay = spreadTime;
		}
		
		override public function update():void{
			super.update();	
		}
		
		public function get spreadTime():Number {
			if (type == "infest"){
				if (tile.tileType == "hospital"){
					return 17 + (FlxG.random() * 12);
				}
				else return 15 + (FlxG.random() * 10);
			}
			return 4.4 + (FlxG.random() * 6);
		}
		
		public function cooldown():void {
			tile.tileRecovered();
			tile.tileEffect = null;
			clear();
			kill();
			if (tile.layeredAbove) GamePlayState.tileEffects2.remove(this);
			else GamePlayState.tileEffects.remove(this);
		}
		
		public function canStillSpread():Boolean{
			return _canSpread;
		}
		
		public function doAction(action:String):void {
			if (action == type){
				if (type == "explode"){
					GamePlayState.rainFire(6);
					FlxG.play(AssetStore.fanFlames);
				}
				else if (type == "infest") {
					if (_monster == null){
						_monster = new Monster(tile);
						
						_monster.setColliderGroup(GamePlayState.monsterColliders);
						GamePlayState.monsters.add(_monster);
					}
					else {
						_monster.evolveToMonster();
						tile.tileEffect = null;
						if (tile.layeredAbove) GamePlayState.tileEffects2.remove(this);
						else GamePlayState.tileEffects.remove(this);	
					}
				}
				else if (type == "fire"){
					if (_monster != null){
						_monster.perish();
					}
				}
			}
			else {
				if (type == "infest"){
					
					this.initialize(tile, action);
				}
				else if (type == "fire"){
					if (action == "explode"){
						this.initialize(tile, action);
						if (_monster != null){
							_monster.perish();
						}
					}
					else if (action == "infest"){
						GamePlayState.rainFire(1);
					}
				}
				else if (type == "explode"){
					GamePlayState.rainFire(3);
					if (_monster != null){
						_monster.perish();
					}
				}
			}
		}
		
		private function checkIfTileIsSpreadable(tile:NiloTile):Boolean {
			if (type != "infest" && tile.tileType == "road") return false;
			if (tile.tileEffect != null) return false;
			return true;
		}
		
		private function checkIfTileIsDefinatelySpreadable(tile:NiloTile):Boolean {
			if (type != "infest"){
				if (tile.tileEffect != null && tile.tileEffect.type == "infest") return true;
			}
			return false;
		}
		
		public function determineGFX():void{
			_sprite.frame = 0;
			if (true){
				var topTile:NiloTile = tile.topTile;
				if (topTile != null) {
					topTile = !(topTile.tileEffect != null && topTile.tileEffect._sprite.visible) ? null : topTile;
				}
				var leftTile:NiloTile = tile.leftTile;
				if (leftTile != null) {
					leftTile = !(leftTile.tileEffect != null && leftTile.tileEffect._sprite.visible) ? null : leftTile;
				}
				var bottomTile:NiloTile = tile.bottomTile;
				if (bottomTile != null) {
					bottomTile = !(bottomTile.tileEffect != null && bottomTile.tileEffect._sprite.visible) ? null : bottomTile;
				}
				var rightTile:NiloTile = tile.rightTile;
				if (rightTile != null) {
					rightTile = !(rightTile.tileEffect != null && rightTile.tileEffect._sprite.visible) ? null : rightTile;
				}
				
				if (topTile == null && leftTile == null && rightTile == null && bottomTile == null){
					_sprite.frame = 0;
				}
				else if(topTile != null && leftTile == null && rightTile == null && bottomTile == null){
					_sprite.frame = 3;
				}
				else if(topTile == null && leftTile != null && rightTile == null && bottomTile == null){
					_sprite.frame = 15;
				}
				else if(topTile == null && leftTile == null && rightTile != null && bottomTile == null){
					_sprite.frame = 13;
				}
				else if(topTile == null && leftTile == null && rightTile == null && bottomTile != null){
					_sprite.frame = 1;
				}
				else if(topTile != null && leftTile != null && rightTile == null && bottomTile == null){
					_sprite.frame = 12;
				}
				else if(topTile != null && leftTile == null && rightTile != null && bottomTile == null){
					_sprite.frame = 10;
				}
				else if(topTile != null && leftTile == null && rightTile == null && bottomTile != null){
					_sprite.frame = 2;
				}
				else if(topTile == null && leftTile != null && rightTile != null && bottomTile == null){
					_sprite.frame = 14;
				}
				else if(topTile == null && leftTile != null && rightTile == null && bottomTile != null){
					_sprite.frame = 6;
				}
				else if(topTile == null && leftTile == null && rightTile != null && bottomTile != null){
					_sprite.frame = 4;
				}
				else if(topTile != null && leftTile != null && rightTile != null && bottomTile == null){
					_sprite.frame = 11;
				}
				else if(topTile != null && leftTile == null && rightTile != null && bottomTile != null){
					_sprite.frame = 7;
				}
				else if(topTile != null && leftTile != null && rightTile == null && bottomTile != null){
					_sprite.frame = 9;
				}
				else if(topTile == null && leftTile != null && rightTile != null && bottomTile != null){
					_sprite.frame = 5;
				}
				else{
					_sprite.frame = 8;
				}
			}
		}
		
		override public function collided(ownCollider:Collider, object:FlxObject):void {
			if (alive){
				if (object is Car){
				var car:Car = object as Car;
				if (_lavaSprite.visible){
					GamePlayState.killSprite(car);
					GamePlayState.applyScore("car", car.x, car.y);
				}
				else if (!car.wrecked && (_flameSprite.visible)){
					car.crash();
					GamePlayState.applyScore("car", car.x, car.y);	
				}
			}
			else if (object is Human){
				var human:Human = object as Human;
				if (!human.isInjured){
					if (_lavaSprite.visible){
						GamePlayState.killSprite(human);
						GamePlayState.applyScore("human", human.x, human.y);
					}
					else if (_flameSprite.visible){
						human.burn();
					}
					else if (_sprite.visible){
						human.infest();
					}
				}
			}
			else if (object is Collider){
				var collider:Collider = object as Collider;
				if (collider.uniqueID == "monster"){
					(collider.parent as Monster).perish();
				}
			}
			}
			
		}
		
		public function acb(name:String, frameN:Number, frameI:Number):void {
			if (name == "infeststart" && frameN == 7){
				_sprite.visible = true;
				remove(_infestAnimation);
				_infestAnimation = null;
				determineGFX();
				tile.determineAdjacent();
			}
		}
		
	}
}
